{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 资本资产定价模型 Capital Asset Pricing Model\n",
    "Alpha and Beta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 股市整体收益率：上证指数\n",
    "- 股票市场整体收益率：所有股票来计算（包含0，3，6开头）\n",
    "- 3开头是深圳创业板 2009开始\n",
    "$$\n",
    "E[R_{i，t}] - R_{f,t}= {β}_i(E[R_{m，t}]) - R_{f,t}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "β_i= Cov(R_{i,t},R_{m,t}) /Var(R_{m,t})\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The CAPM predicts that cross-sectional variation in the expected returns of different securities is driven only by cross-sectional variation in the betas of the securities.\n",
    "\n",
    "在横截面上，所有股票预期收益率的变化只来源于股票贝塔的变化。\n",
    "\n",
    "The first group of tests examines the cross-sectional ability of beta to predict the future excess returns.\n",
    "\n",
    "第一类方式：检验个股贝塔预测未来的股票收益率\n",
    "\n",
    "The second group of tests examines the cross-sectional ability of other variables to predict future excess returns.\n",
    "\n",
    "第二类方式：检验其他能够预测个股未来回报率指标的能力\n",
    "\n",
    "Size 规模\n",
    "EP 盈利/市值比率\n",
    "To 换手率\n",
    "The second empirically testable prediction of the CAPM is that the average excess returns, after accounting for the effect of beta, should be zero. To test this hypothesis, researchers frequently examine the intercept term of cross-sectional regressions of security excess returns on estimates of beta.\n",
    "\n",
    "CAPM模型另一个实证的检验标准是：横截面上所有股票的变化能够完全被贝塔解释掉，所以在考虑了贝塔的影响之后，没有额外的回报率，即没有α。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用贝塔构造投资组合\n",
    "t月的高贝塔股票在t+1月能否获得更高的回报率，相比于低贝塔股票"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np # 数据处理最重要的模块\n",
    "import pandas as pd # 数据处理最重要的模块\n",
    "import scipy.stats as stats # 统计模块\n",
    "import scipy\n",
    "# import pymysql  # 导入数据库模块\n",
    "\n",
    "from datetime import datetime # 时间模块\n",
    "import statsmodels.formula.api as smf  # OLS regression\n",
    "\n",
    "# import pyreadr # read RDS file\n",
    "\n",
    "from matplotlib import style\n",
    "import matplotlib.pyplot as plt  # 画图模块\n",
    "import matplotlib.dates as mdates\n",
    "\n",
    "from matplotlib.font_manager import FontProperties # 作图中文\n",
    "from pylab import mpl\n",
    "#mpl.rcParams['font.sans-serif'] = ['SimHei']\n",
    "#plt.rcParams['font.family'] = 'Times New Roman'\n",
    "\n",
    "#输出矢量图 渲染矢量图\n",
    "%matplotlib inline\n",
    "%config InlineBackend.figure_format = 'svg'\n",
    "\n",
    "from IPython.core.interactiveshell import InteractiveShell # jupyter运行输出的模块\n",
    "#显示每一个运行结果\n",
    "InteractiveShell.ast_node_interactivity = 'all'\n",
    "\n",
    "#设置行不限制数量\n",
    "#pd.set_option('display.max_rows',None)\n",
    "\n",
    "#设置列不限制数量\n",
    "pd.set_option('display.max_columns', None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Stkcd</th>\n",
       "      <th>month</th>\n",
       "      <th>price</th>\n",
       "      <th>Rank</th>\n",
       "      <th>Freq</th>\n",
       "      <th>floatingvalue</th>\n",
       "      <th>totalvalue</th>\n",
       "      <th>sizef</th>\n",
       "      <th>sizet</th>\n",
       "      <th>Return</th>\n",
       "      <th>rfmonth</th>\n",
       "      <th>ret</th>\n",
       "      <th>next_ret</th>\n",
       "      <th>w</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-05-31</td>\n",
       "      <td>38.34</td>\n",
       "      <td>2</td>\n",
       "      <td>24.0</td>\n",
       "      <td>1.016010e+09</td>\n",
       "      <td>1.859497e+09</td>\n",
       "      <td>20.739149</td>\n",
       "      <td>21.343572</td>\n",
       "      <td>-0.122253</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.128345</td>\n",
       "      <td>-0.119551</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-06-30</td>\n",
       "      <td>33.99</td>\n",
       "      <td>3</td>\n",
       "      <td>23.0</td>\n",
       "      <td>9.007350e+08</td>\n",
       "      <td>1.648521e+09</td>\n",
       "      <td>20.618722</td>\n",
       "      <td>21.223144</td>\n",
       "      <td>-0.113459</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.119551</td>\n",
       "      <td>-0.137013</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-07-31</td>\n",
       "      <td>29.54</td>\n",
       "      <td>4</td>\n",
       "      <td>16.0</td>\n",
       "      <td>7.828100e+08</td>\n",
       "      <td>1.432695e+09</td>\n",
       "      <td>20.478401</td>\n",
       "      <td>21.082823</td>\n",
       "      <td>-0.130921</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.137013</td>\n",
       "      <td>-0.417680</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-08-31</td>\n",
       "      <td>15.00</td>\n",
       "      <td>5</td>\n",
       "      <td>15.0</td>\n",
       "      <td>6.748338e+08</td>\n",
       "      <td>1.346275e+09</td>\n",
       "      <td>20.329977</td>\n",
       "      <td>21.020607</td>\n",
       "      <td>-0.411588</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.417680</td>\n",
       "      <td>-0.039425</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-09-30</td>\n",
       "      <td>14.50</td>\n",
       "      <td>6</td>\n",
       "      <td>24.0</td>\n",
       "      <td>6.523394e+08</td>\n",
       "      <td>1.301399e+09</td>\n",
       "      <td>20.296075</td>\n",
       "      <td>20.986706</td>\n",
       "      <td>-0.033333</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.039425</td>\n",
       "      <td>0.849080</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>752023</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-08-31</td>\n",
       "      <td>13.56</td>\n",
       "      <td>24</td>\n",
       "      <td>23.0</td>\n",
       "      <td>7.955351e+09</td>\n",
       "      <td>1.054667e+10</td>\n",
       "      <td>22.797111</td>\n",
       "      <td>23.079076</td>\n",
       "      <td>-0.025862</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.027103</td>\n",
       "      <td>0.071030</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>752024</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-09-30</td>\n",
       "      <td>14.54</td>\n",
       "      <td>25</td>\n",
       "      <td>20.0</td>\n",
       "      <td>8.530295e+09</td>\n",
       "      <td>1.130889e+10</td>\n",
       "      <td>22.866890</td>\n",
       "      <td>23.148855</td>\n",
       "      <td>0.072271</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>0.071030</td>\n",
       "      <td>-0.048696</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>752025</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-10-31</td>\n",
       "      <td>13.85</td>\n",
       "      <td>26</td>\n",
       "      <td>17.0</td>\n",
       "      <td>8.125488e+09</td>\n",
       "      <td>1.077222e+10</td>\n",
       "      <td>22.818272</td>\n",
       "      <td>23.100237</td>\n",
       "      <td>-0.047455</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.048696</td>\n",
       "      <td>-0.027956</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>752026</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-11-30</td>\n",
       "      <td>13.48</td>\n",
       "      <td>27</td>\n",
       "      <td>22.0</td>\n",
       "      <td>7.908417e+09</td>\n",
       "      <td>1.048444e+10</td>\n",
       "      <td>22.791193</td>\n",
       "      <td>23.073159</td>\n",
       "      <td>-0.026715</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.027956</td>\n",
       "      <td>0.103358</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>752027</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-12-31</td>\n",
       "      <td>14.89</td>\n",
       "      <td>28</td>\n",
       "      <td>21.0</td>\n",
       "      <td>8.735632e+09</td>\n",
       "      <td>1.158111e+10</td>\n",
       "      <td>22.890676</td>\n",
       "      <td>23.172641</td>\n",
       "      <td>0.104599</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>0.103358</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>709883 rows × 14 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "         Stkcd      month  price  Rank  Freq  floatingvalue    totalvalue  \\\n",
       "1       000001 1991-05-31  38.34     2  24.0   1.016010e+09  1.859497e+09   \n",
       "2       000001 1991-06-30  33.99     3  23.0   9.007350e+08  1.648521e+09   \n",
       "3       000001 1991-07-31  29.54     4  16.0   7.828100e+08  1.432695e+09   \n",
       "4       000001 1991-08-31  15.00     5  15.0   6.748338e+08  1.346275e+09   \n",
       "5       000001 1991-09-30  14.50     6  24.0   6.523394e+08  1.301399e+09   \n",
       "...        ...        ...    ...   ...   ...            ...           ...   \n",
       "752023  605599 2023-08-31  13.56    24  23.0   7.955351e+09  1.054667e+10   \n",
       "752024  605599 2023-09-30  14.54    25  20.0   8.530295e+09  1.130889e+10   \n",
       "752025  605599 2023-10-31  13.85    26  17.0   8.125488e+09  1.077222e+10   \n",
       "752026  605599 2023-11-30  13.48    27  22.0   7.908417e+09  1.048444e+10   \n",
       "752027  605599 2023-12-31  14.89    28  21.0   8.735632e+09  1.158111e+10   \n",
       "\n",
       "            sizef      sizet    Return   rfmonth       ret  next_ret  w  \n",
       "1       20.739149  21.343572 -0.122253  0.006092 -0.128345 -0.119551  1  \n",
       "2       20.618722  21.223144 -0.113459  0.006092 -0.119551 -0.137013  1  \n",
       "3       20.478401  21.082823 -0.130921  0.006092 -0.137013 -0.417680  1  \n",
       "4       20.329977  21.020607 -0.411588  0.006092 -0.417680 -0.039425  1  \n",
       "5       20.296075  20.986706 -0.033333  0.006092 -0.039425  0.849080  1  \n",
       "...           ...        ...       ...       ...       ...       ... ..  \n",
       "752023  22.797111  23.079076 -0.025862  0.001241 -0.027103  0.071030  1  \n",
       "752024  22.866890  23.148855  0.072271  0.001241  0.071030 -0.048696  1  \n",
       "752025  22.818272  23.100237 -0.047455  0.001241 -0.048696 -0.027956  1  \n",
       "752026  22.791193  23.073159 -0.026715  0.001241 -0.027956  0.103358  1  \n",
       "752027  22.890676  23.172641  0.104599  0.001241  0.103358       NaN  1  \n",
       "\n",
       "[709883 rows x 14 columns]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cross = pd.read_csv('C:/Users/21230/Desktop/Python-homework/python-homework-ykl-1/ret_mon_python2023.csv')\n",
    "from pandas.tseries.offsets import MonthEnd\n",
    "cross['month'] = pd.to_datetime(cross['month'], format='%Y-%m-%d') + MonthEnd(1)\n",
    "# 补齐股票代码 如果不满6位 在前面补上0\n",
    "cross['Stkcd'] = cross['Stkcd'].apply(lambda x: '{:0>6}'.format(x)) # 6位股票代码\n",
    "cross['w'] = 1\n",
    "cross = cross.dropna(subset=['ret'])\n",
    "cross"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 导入市场收益率数据\n",
    "注意这和上证指数计算的收益率不同，但同样是市场层面数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "MKT_{t} = R_{m,t} - R_{f,t}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>month</th>\n",
       "      <th>MarketR</th>\n",
       "      <th>MarketR_e</th>\n",
       "      <th>rfmonth</th>\n",
       "      <th>MKT</th>\n",
       "      <th>ret_e</th>\n",
       "      <th>marketret3</th>\n",
       "      <th>marketret6</th>\n",
       "      <th>marketret12</th>\n",
       "      <th>Q</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1991-01-31</td>\n",
       "      <td>0.029998</td>\n",
       "      <td>0.036554</td>\n",
       "      <td>0.006930</td>\n",
       "      <td>0.023068</td>\n",
       "      <td>0.029624</td>\n",
       "      <td>-0.084127</td>\n",
       "      <td>-0.305662</td>\n",
       "      <td>0.254049</td>\n",
       "      <td>1991 Q1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1991-02-28</td>\n",
       "      <td>0.010203</td>\n",
       "      <td>0.021860</td>\n",
       "      <td>0.006930</td>\n",
       "      <td>0.003273</td>\n",
       "      <td>0.014930</td>\n",
       "      <td>-0.183573</td>\n",
       "      <td>-0.384745</td>\n",
       "      <td>0.241492</td>\n",
       "      <td>1991 Q1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1991-03-31</td>\n",
       "      <td>-0.099663</td>\n",
       "      <td>-0.060425</td>\n",
       "      <td>0.006930</td>\n",
       "      <td>-0.106593</td>\n",
       "      <td>-0.067355</td>\n",
       "      <td>-0.252928</td>\n",
       "      <td>-0.445049</td>\n",
       "      <td>0.288857</td>\n",
       "      <td>1991 Q1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1991-04-30</td>\n",
       "      <td>-0.079652</td>\n",
       "      <td>-0.031449</td>\n",
       "      <td>0.006651</td>\n",
       "      <td>-0.086303</td>\n",
       "      <td>-0.038100</td>\n",
       "      <td>-0.234776</td>\n",
       "      <td>-0.394937</td>\n",
       "      <td>0.691749</td>\n",
       "      <td>1991 Q2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1991-05-31</td>\n",
       "      <td>-0.074521</td>\n",
       "      <td>0.005375</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.080613</td>\n",
       "      <td>-0.000717</td>\n",
       "      <td>-0.236294</td>\n",
       "      <td>0.181673</td>\n",
       "      <td>1.542701</td>\n",
       "      <td>1991 Q2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>391</th>\n",
       "      <td>2023-08-31</td>\n",
       "      <td>-0.055570</td>\n",
       "      <td>-0.041538</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.056811</td>\n",
       "      <td>-0.042779</td>\n",
       "      <td>-0.089387</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2023 Q3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>392</th>\n",
       "      <td>2023-09-30</td>\n",
       "      <td>-0.005689</td>\n",
       "      <td>0.000357</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.006930</td>\n",
       "      <td>-0.000884</td>\n",
       "      <td>-0.033855</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2023 Q3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>393</th>\n",
       "      <td>2023-10-31</td>\n",
       "      <td>-0.026321</td>\n",
       "      <td>-0.009959</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.027562</td>\n",
       "      <td>-0.011200</td>\n",
       "      <td>-0.047817</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2023 Q4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>394</th>\n",
       "      <td>2023-11-30</td>\n",
       "      <td>0.001790</td>\n",
       "      <td>0.034280</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>0.000549</td>\n",
       "      <td>0.033039</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2023 Q4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>395</th>\n",
       "      <td>2023-12-31</td>\n",
       "      <td>-0.020003</td>\n",
       "      <td>-0.020632</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.021244</td>\n",
       "      <td>-0.021873</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2023 Q4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>396 rows × 10 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "         month   MarketR  MarketR_e   rfmonth       MKT     ret_e  marketret3  \\\n",
       "0   1991-01-31  0.029998   0.036554  0.006930  0.023068  0.029624   -0.084127   \n",
       "1   1991-02-28  0.010203   0.021860  0.006930  0.003273  0.014930   -0.183573   \n",
       "2   1991-03-31 -0.099663  -0.060425  0.006930 -0.106593 -0.067355   -0.252928   \n",
       "3   1991-04-30 -0.079652  -0.031449  0.006651 -0.086303 -0.038100   -0.234776   \n",
       "4   1991-05-31 -0.074521   0.005375  0.006092 -0.080613 -0.000717   -0.236294   \n",
       "..         ...       ...        ...       ...       ...       ...         ...   \n",
       "391 2023-08-31 -0.055570  -0.041538  0.001241 -0.056811 -0.042779   -0.089387   \n",
       "392 2023-09-30 -0.005689   0.000357  0.001241 -0.006930 -0.000884   -0.033855   \n",
       "393 2023-10-31 -0.026321  -0.009959  0.001241 -0.027562 -0.011200   -0.047817   \n",
       "394 2023-11-30  0.001790   0.034280  0.001241  0.000549  0.033039         NaN   \n",
       "395 2023-12-31 -0.020003  -0.020632  0.001241 -0.021244 -0.021873         NaN   \n",
       "\n",
       "     marketret6  marketret12        Q  \n",
       "0     -0.305662     0.254049  1991 Q1  \n",
       "1     -0.384745     0.241492  1991 Q1  \n",
       "2     -0.445049     0.288857  1991 Q1  \n",
       "3     -0.394937     0.691749  1991 Q2  \n",
       "4      0.181673     1.542701  1991 Q2  \n",
       "..          ...          ...      ...  \n",
       "391         NaN          NaN  2023 Q3  \n",
       "392         NaN          NaN  2023 Q3  \n",
       "393         NaN          NaN  2023 Q4  \n",
       "394         NaN          NaN  2023 Q4  \n",
       "395         NaN          NaN  2023 Q4  \n",
       "\n",
       "[396 rows x 10 columns]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Market_ret = pd.read_excel('python-homework-ykl-1/Marketret_mon_stock2023.xlsx')\n",
    "Market_ret['month'] = pd.to_datetime(Market_ret['month'],format='%b %Y') + MonthEnd(1)\n",
    "Market_ret.rename(columns={'ret':'MKT'}, inplace=True)\n",
    "Market_ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Stkcd</th>\n",
       "      <th>month</th>\n",
       "      <th>price</th>\n",
       "      <th>Rank</th>\n",
       "      <th>Freq</th>\n",
       "      <th>floatingvalue</th>\n",
       "      <th>totalvalue</th>\n",
       "      <th>sizef</th>\n",
       "      <th>sizet</th>\n",
       "      <th>Return</th>\n",
       "      <th>rfmonth</th>\n",
       "      <th>ret</th>\n",
       "      <th>next_ret</th>\n",
       "      <th>w</th>\n",
       "      <th>MKT</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-05-31</td>\n",
       "      <td>38.34</td>\n",
       "      <td>2</td>\n",
       "      <td>24.0</td>\n",
       "      <td>1.016010e+09</td>\n",
       "      <td>1.859497e+09</td>\n",
       "      <td>20.739149</td>\n",
       "      <td>21.343572</td>\n",
       "      <td>-0.122253</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.128345</td>\n",
       "      <td>-0.119551</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.080613</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-06-30</td>\n",
       "      <td>33.99</td>\n",
       "      <td>3</td>\n",
       "      <td>23.0</td>\n",
       "      <td>9.007350e+08</td>\n",
       "      <td>1.648521e+09</td>\n",
       "      <td>20.618722</td>\n",
       "      <td>21.223144</td>\n",
       "      <td>-0.113459</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.119551</td>\n",
       "      <td>-0.137013</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.085440</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-07-31</td>\n",
       "      <td>29.54</td>\n",
       "      <td>4</td>\n",
       "      <td>16.0</td>\n",
       "      <td>7.828100e+08</td>\n",
       "      <td>1.432695e+09</td>\n",
       "      <td>20.478401</td>\n",
       "      <td>21.082823</td>\n",
       "      <td>-0.130921</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.137013</td>\n",
       "      <td>-0.417680</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.088189</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-08-31</td>\n",
       "      <td>15.00</td>\n",
       "      <td>5</td>\n",
       "      <td>15.0</td>\n",
       "      <td>6.748338e+08</td>\n",
       "      <td>1.346275e+09</td>\n",
       "      <td>20.329977</td>\n",
       "      <td>21.020607</td>\n",
       "      <td>-0.411588</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.417680</td>\n",
       "      <td>-0.039425</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.090277</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>000001</td>\n",
       "      <td>1991-09-30</td>\n",
       "      <td>14.50</td>\n",
       "      <td>6</td>\n",
       "      <td>24.0</td>\n",
       "      <td>6.523394e+08</td>\n",
       "      <td>1.301399e+09</td>\n",
       "      <td>20.296075</td>\n",
       "      <td>20.986706</td>\n",
       "      <td>-0.033333</td>\n",
       "      <td>0.006092</td>\n",
       "      <td>-0.039425</td>\n",
       "      <td>0.849080</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.031046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>709878</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-08-31</td>\n",
       "      <td>13.56</td>\n",
       "      <td>24</td>\n",
       "      <td>23.0</td>\n",
       "      <td>7.955351e+09</td>\n",
       "      <td>1.054667e+10</td>\n",
       "      <td>22.797111</td>\n",
       "      <td>23.079076</td>\n",
       "      <td>-0.025862</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.027103</td>\n",
       "      <td>0.071030</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.056811</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>709879</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-09-30</td>\n",
       "      <td>14.54</td>\n",
       "      <td>25</td>\n",
       "      <td>20.0</td>\n",
       "      <td>8.530295e+09</td>\n",
       "      <td>1.130889e+10</td>\n",
       "      <td>22.866890</td>\n",
       "      <td>23.148855</td>\n",
       "      <td>0.072271</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>0.071030</td>\n",
       "      <td>-0.048696</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.006930</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>709880</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-10-31</td>\n",
       "      <td>13.85</td>\n",
       "      <td>26</td>\n",
       "      <td>17.0</td>\n",
       "      <td>8.125488e+09</td>\n",
       "      <td>1.077222e+10</td>\n",
       "      <td>22.818272</td>\n",
       "      <td>23.100237</td>\n",
       "      <td>-0.047455</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.048696</td>\n",
       "      <td>-0.027956</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.027562</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>709881</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-11-30</td>\n",
       "      <td>13.48</td>\n",
       "      <td>27</td>\n",
       "      <td>22.0</td>\n",
       "      <td>7.908417e+09</td>\n",
       "      <td>1.048444e+10</td>\n",
       "      <td>22.791193</td>\n",
       "      <td>23.073159</td>\n",
       "      <td>-0.026715</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>-0.027956</td>\n",
       "      <td>0.103358</td>\n",
       "      <td>1</td>\n",
       "      <td>0.000549</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>709882</th>\n",
       "      <td>605599</td>\n",
       "      <td>2023-12-31</td>\n",
       "      <td>14.89</td>\n",
       "      <td>28</td>\n",
       "      <td>21.0</td>\n",
       "      <td>8.735632e+09</td>\n",
       "      <td>1.158111e+10</td>\n",
       "      <td>22.890676</td>\n",
       "      <td>23.172641</td>\n",
       "      <td>0.104599</td>\n",
       "      <td>0.001241</td>\n",
       "      <td>0.103358</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.021244</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>709883 rows × 15 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "         Stkcd      month  price  Rank  Freq  floatingvalue    totalvalue  \\\n",
       "0       000001 1991-05-31  38.34     2  24.0   1.016010e+09  1.859497e+09   \n",
       "1       000001 1991-06-30  33.99     3  23.0   9.007350e+08  1.648521e+09   \n",
       "2       000001 1991-07-31  29.54     4  16.0   7.828100e+08  1.432695e+09   \n",
       "3       000001 1991-08-31  15.00     5  15.0   6.748338e+08  1.346275e+09   \n",
       "4       000001 1991-09-30  14.50     6  24.0   6.523394e+08  1.301399e+09   \n",
       "...        ...        ...    ...   ...   ...            ...           ...   \n",
       "709878  605599 2023-08-31  13.56    24  23.0   7.955351e+09  1.054667e+10   \n",
       "709879  605599 2023-09-30  14.54    25  20.0   8.530295e+09  1.130889e+10   \n",
       "709880  605599 2023-10-31  13.85    26  17.0   8.125488e+09  1.077222e+10   \n",
       "709881  605599 2023-11-30  13.48    27  22.0   7.908417e+09  1.048444e+10   \n",
       "709882  605599 2023-12-31  14.89    28  21.0   8.735632e+09  1.158111e+10   \n",
       "\n",
       "            sizef      sizet    Return   rfmonth       ret  next_ret  w  \\\n",
       "0       20.739149  21.343572 -0.122253  0.006092 -0.128345 -0.119551  1   \n",
       "1       20.618722  21.223144 -0.113459  0.006092 -0.119551 -0.137013  1   \n",
       "2       20.478401  21.082823 -0.130921  0.006092 -0.137013 -0.417680  1   \n",
       "3       20.329977  21.020607 -0.411588  0.006092 -0.417680 -0.039425  1   \n",
       "4       20.296075  20.986706 -0.033333  0.006092 -0.039425  0.849080  1   \n",
       "...           ...        ...       ...       ...       ...       ... ..   \n",
       "709878  22.797111  23.079076 -0.025862  0.001241 -0.027103  0.071030  1   \n",
       "709879  22.866890  23.148855  0.072271  0.001241  0.071030 -0.048696  1   \n",
       "709880  22.818272  23.100237 -0.047455  0.001241 -0.048696 -0.027956  1   \n",
       "709881  22.791193  23.073159 -0.026715  0.001241 -0.027956  0.103358  1   \n",
       "709882  22.890676  23.172641  0.104599  0.001241  0.103358       NaN  1   \n",
       "\n",
       "             MKT  \n",
       "0      -0.080613  \n",
       "1      -0.085440  \n",
       "2      -0.088189  \n",
       "3      -0.090277  \n",
       "4      -0.031046  \n",
       "...          ...  \n",
       "709878 -0.056811  \n",
       "709879 -0.006930  \n",
       "709880 -0.027562  \n",
       "709881  0.000549  \n",
       "709882 -0.021244  \n",
       "\n",
       "[709883 rows x 15 columns]"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cross = pd.merge(cross,Market_ret[['month','MKT']],left_on='month',right_on='month',how='left')\n",
    "cross"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 估计个股的β\n",
    "使用t月前60个月的月数据来滚动回归估计个股β"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import statsmodels.api as sm\n",
    "\n",
    "# 假设我们有一个DataFrame 'data'，其中包含个股和市场的月度收益率\n",
    "# 'data' 包含四列：'month'（月份），'Stkcd'（股票代码），'stock_return'（个股收益率），'market_return'（市场收益率）\n",
    "\n",
    "# 定义一个函数来计算滚动回归的贝塔和使用的数据点数量\n",
    "def rolling_beta_per_stock(data, window_months=60):\n",
    "    betas = []\n",
    "    months = []\n",
    "    Stkcds = []\n",
    "    data_counts = []\n",
    "    \n",
    "    # 按股票分组\n",
    "    grouped = data.groupby('Stkcd')\n",
    "    \n",
    "    for Stkcd, group in grouped:\n",
    "        group = group.set_index('month').sort_index()\n",
    "        end_months = group.index.unique()\n",
    "        \n",
    "        for end_month in end_months:\n",
    "            start_month = end_month - pd.DateOffset(months=window_months)\n",
    "            window_data = group.loc[start_month:end_month]\n",
    "            \n",
    "            if len(window_data) > 0:\n",
    "                X = sm.add_constant(window_data['MKT'])\n",
    "                y = window_data['ret']\n",
    "                model = sm.OLS(y, X).fit()\n",
    "                \n",
    "                beta = model.params['MKT']\n",
    "                betas.append(beta)\n",
    "                months.append(end_month)\n",
    "                Stkcds.append(Stkcd)\n",
    "                data_counts.append(len(window_data))  # 记录使用的数据点数量\n",
    "    \n",
    "    return pd.DataFrame({'Stkcd': Stkcds, 'month': months, 'beta': betas, 'data_count': data_counts})\n",
    "\n",
    "# 计算每只股票的滚动贝塔和数据点数量\n",
    "rolling_betas = rolling_beta_per_stock(cross)\n",
    "\n",
    "# 打印结果\n",
    "print(rolling_betas)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'rolling_betas' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[20], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# save rolling_betas\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m rolling_betas\u001b[38;5;241m.\u001b[39mto_csv(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mC:/Users/21230/Desktop/Python-homework/python-homework-ykl-1/rolling_betas.csv\u001b[39m\u001b[38;5;124m'\u001b[39m, index\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[0;32m      3\u001b[0m cross_beta \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mmerge(cross,rolling_betas,on\u001b[38;5;241m=\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mStkcd\u001b[39m\u001b[38;5;124m\"\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmonth\u001b[39m\u001b[38;5;124m'\u001b[39m),how\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mleft\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m      4\u001b[0m cross_beta\n",
      "\u001b[1;31mNameError\u001b[0m: name 'rolling_betas' is not defined"
     ]
    }
   ],
   "source": [
    "# save rolling_betas\n",
    "rolling_betas.to_csv('C:/Users/21230/Desktop/Python-homework/python-homework-ykl-1/rolling_betas.csv', index=False)\n",
    "cross_beta = pd.merge(cross,rolling_betas,on=(\"Stkcd\",'month'),how='left')\n",
    "cross_beta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'cross_beta' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[21], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m fenweishu \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mDataFrame(\n\u001b[1;32m----> 2\u001b[0m     cross_beta\u001b[38;5;241m.\u001b[39mgroupby([\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmonth\u001b[39m\u001b[38;5;124m'\u001b[39m])[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbeta\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mquantile([\u001b[38;5;241m0.1\u001b[39m,\u001b[38;5;241m0.2\u001b[39m,\u001b[38;5;241m0.3\u001b[39m,\u001b[38;5;241m0.4\u001b[39m,\u001b[38;5;241m0.5\u001b[39m,\u001b[38;5;241m0.6\u001b[39m,\u001b[38;5;241m0.7\u001b[39m,\u001b[38;5;241m0.8\u001b[39m,\u001b[38;5;241m0.9\u001b[39m]))\n\u001b[0;32m      3\u001b[0m fenweishu \u001b[38;5;241m=\u001b[39m fenweishu\u001b[38;5;241m.\u001b[39mreset_index()\n\u001b[0;32m      4\u001b[0m fenweishu \u001b[38;5;241m=\u001b[39m fenweishu\u001b[38;5;241m.\u001b[39mpivot_table(index\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmonth\u001b[39m\u001b[38;5;124m'\u001b[39m,columns\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mlevel_1\u001b[39m\u001b[38;5;124m'\u001b[39m,values\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbeta\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
      "\u001b[1;31mNameError\u001b[0m: name 'cross_beta' is not defined"
     ]
    }
   ],
   "source": [
    "fenweishu = pd.DataFrame(\n",
    "    cross_beta.groupby(['month'])['beta'].quantile([0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]))\n",
    "fenweishu = fenweishu.reset_index()\n",
    "fenweishu = fenweishu.pivot_table(index='month',columns='level_1',values='beta')\n",
    "fenweishu.columns = ['one','two','three','four','five','six','seven','eight','nine']\n",
    "fenweishu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "portfolio = pd.merge(cross_beta,fenweishu,on='month')\n",
    "portfolio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "portfolio['sort'] = np.where(\n",
    "    portfolio['beta'] <= portfolio['one'], 'P1',\n",
    "    np.where(\n",
    "        portfolio['beta'] <= portfolio['two'], 'P2',\n",
    "        np.where(\n",
    "            portfolio['beta'] <= portfolio['three'], 'P3',\n",
    "            np.where(\n",
    "                portfolio['beta'] <= portfolio['four'], 'P4',\n",
    "                np.where(\n",
    "                    portfolio['beta'] <= portfolio['five'], 'P5',\n",
    "                    np.where(\n",
    "                        portfolio['beta'] <= portfolio['six'], 'P6',\n",
    "                        np.where(\n",
    "                            portfolio['beta'] <= portfolio['seven'], 'P7',\n",
    "                            np.where(\n",
    "                                portfolio['beta'] <= portfolio['eight'], 'P8',\n",
    "                                np.where(\n",
    "                                    portfolio['beta'] <= portfolio['nine'],\n",
    "                                    'P9', 'Pmax')))))))))\n",
    "portfolio = portfolio.dropna(subset=['floatingvalue','next_ret','beta'])\n",
    "portfolio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "portfolio = portfolio.dropna(subset=['next_ret','floatingvalue','beta'])\n",
    "portfolio_beta =  pd.DataFrame(\n",
    "    portfolio.groupby(['month','sort']).apply(lambda x: np.average(x['next_ret'],weights = x['floatingvalue']),include_groups=False))\n",
    "portfolio_beta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "portfolio_beta = portfolio_beta.reset_index()\n",
    "portfolio_beta.columns = ['month', 'sort', 'p']\n",
    "portfolio_beta['month'] = portfolio_beta['month'] + MonthEnd(1)\n",
    "portfolio_beta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "portfolio_beta = portfolio_beta.pivot_table(index='month',\n",
    "                                            columns='sort',\n",
    "                                            values='p')\n",
    "portfolio_beta['My_portfolio'] = portfolio_beta['Pmax'] - portfolio_beta['P1']\n",
    "portfolio_beta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "portfolio_beta = portfolio_beta['1995-01':'2023-12']\n",
    "portfolio_beta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = smf.ols('My_portfolio ~ 1',\n",
    "                 data=portfolio_beta['1995-01':'2023-12']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model.summary())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cross_beta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cross_beta2 = cross_beta[cross_beta['data_count'] >= 48].copy()\n",
    "cross_beta2 = cross_beta2.set_index(['Stkcd', 'month']) # 设置multi-index\n",
    "cross_beta2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from linearmodels import FamaMacBeth\n",
    "model = FamaMacBeth.from_formula('next_ret ~ 1 + beta', data=cross_beta2.dropna(subset=['next_ret','beta']))\n",
    "## 一般fm回归结果展示的是Newey-West调整后的t值，.fit()中做如下设置\n",
    "## 其中`bandwidth`是Newey-West滞后阶数，选取方式为lag = 4(T/100) ^ (2/9)\n",
    "## 若不需要Newey-West调整则去掉括号内所有设置。\n",
    "# choose bandwidth auto\n",
    "res = model.fit(cov_type= 'kernel',debiased = False,bandwidth=6)\n",
    "print(res.summary)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 是否存在α"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cross_beta2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import statsmodels.api as sm \n",
    "\n",
    "def Fama_MacBeth(data, yvar, xvars):\n",
    "    Y = data[yvar]\n",
    "    X = data[xvars]\n",
    "    X['intercept'] = 1.\n",
    "    result = sm.OLS(Y, X).fit()\n",
    "    return result.params\n",
    "\n",
    "coef = cross_beta2.dropna(subset=['next_ret','beta']).groupby('month').apply(Fama_MacBeth, 'next_ret', ['beta'])\n",
    "coef"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_alpha = smf.ols('intercept ~ 1',\n",
    "                 data=coef['1994-12':'2023-11']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model_alpha.summary())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_beta = smf.ols('beta ~ 1',\n",
    "                 data=coef['1995-12':'2022-11']).fit(\n",
    "                     cov_type='HAC', cov_kwds={'maxlags': 6})\n",
    "print(model_beta.summary())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
